package com.ljc.jsouphttpclient;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Date: 2023/10/31
 * @Author: clj
 * @Description: 网页采集遇到登录，怎么办
 * 豆瓣个人主页为例
 * 1. 手动设置cookie
 * 2. 模拟登录
 * todo: 模拟登录遇到图形验证码如何跳过
 */
public class CrawlerLogin {


    public static void main(String[] args) throws Exception {
        // 个人中心url
        String userInfoUrl = "https://www.douban.com/people/166216831/";

        // 登陆接口
        String loginUrl = "https://accounts.douban.com/j/mobile/login/basic";

//        new CrawlerLogin().setCookies(userInfoUrl);
//        new CrawlerLogin().jsoupLogin(loginUrl, userInfoUrl);
        new CrawlerLogin().httpClientLogin(loginUrl,userInfoUrl);
    }

    /**
     * 手动设置 cookies
     * 先从网站上登录，然后查看 request headers 里面的 cookies
     *
     * @param url
     */
    public void setCookies(String url) throws IOException {
        Document document = Jsoup.connect(url)
                // 手动设置cookies
                .header("Cookie", "bid=NdNFQ9EhJso; ll=\"118163\"; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1698733085%2C%22https%3A%2F%2Fwww.google.com%2F%22%5D; _pk_id.100001.8cb4=1ba7949a97b8138a.1698733085.; _pk_ses.100001.8cb4=1; __utma=30149280.279434367.1698733086.1698733086.1698733086.1; __utmc=30149280; __utmz=30149280.1698733086.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __utmt=1; ap_v=0,6.0; push_noty_num=0; push_doumail_num=0; __utmv=30149280.16621; dbcl2=\"166216831:wjVUrlhWYhs\"; ck=_GUN; __utmb=30149280.17.10.1698733086")
                .get();

        if (document != null) {
            // 获取豆瓣昵称节点
            Element element = document.select(".info h1").first();
            if (element == null) {
                System.out.println("没有找到 .info h1 标签");
                return;
            }
            // 取出豆瓣节点昵称
            String userName = element.ownText();
            System.out.println("豆瓣我的网名为：" + userName);
        } else {
            System.out.println("出错啦！！！！！");
        }
    }

    /**
     * Jsoup 模拟登录豆瓣 访问个人中心
     * 在豆瓣登录时先输入一个错误的账号密码，查看到登录所需要的参数
     * 先构造登录请求参数，成功后获取到cookies
     * 设置request cookies，再次请求
     * todo: 模拟登陆并未成功
     *
     * @param loginUrl    登录url
     * @param userInfoUrl 个人中心url
     * @throws IOException
     */
    public void jsoupLogin(String loginUrl, String userInfoUrl) throws IOException {

        // 登录数据
        Map<String, String> data = new HashMap<>();
        data.put("name", "18021283352");
        data.put("password", "dxy@170701");
        data.put("remember", "false");
        data.put("ticket","");
        data.put("randstr","");
        data.put("tc_app_id","2044348370");
        Connection.Response login = Jsoup.connect(loginUrl)
                .ignoreContentType(true) // 忽略类型验证
                .followRedirects(false) // 禁止重定向
                .postDataCharset("utf-8")
                .header("Upgrade-Insecure-Requests","1")
                .header("Accept","application/json")
                .header("Content-Type","application/x-www-form-urlencoded")
                .header("X-Requested-With","XMLHttpRequest")
                .header("User-Agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36")
                .data(data)
                .method(Connection.Method.POST)
                .execute();
        login.charset("UTF-8");
        // login 中已经获取到登录成功之后的cookies
        // 构造访问个人中心的请求
        Document document = Jsoup.connect(userInfoUrl)
                // 取出login对象里面的cookies
                .cookies(login.cookies())
                .get();
        if (document != null) {
            Element element = document.select(".info h1").first();
            if (element == null) {
                System.out.println("没有找到 .info h1 标签");
                return;
            }
            String userName = element.ownText();
            System.out.println("豆瓣我的网名为：" + userName);
        } else {
            System.out.println("出错啦！！！！！");
        }
    }

    /**
     * httpclient 的方式模拟登录豆瓣
     * httpclient 跟jsoup差不多，不同的地方在于 httpclient 有session的概念
     * 在同一个httpclient 内不需要设置cookies ，会默认缓存下来
     *
     * @param loginUrl
     * @param userInfoUrl
     */
    public void httpClientLogin(String loginUrl, String userInfoUrl) throws Exception {

        CloseableHttpClient httpclient = HttpClients.createDefault();


        HttpUriRequest login = RequestBuilder.post()
                .setUri(new URI(loginUrl))// 登陆url
                .setHeader("Upgrade-Insecure-Requests", "1")
                .setHeader("Accept", "application/json")
                .setHeader("Content-Type", "application/x-www-form-urlencoded")
                .setHeader("X-Requested-With", "XMLHttpRequest")
                .setHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36")
                // 设置账号信息
                .addParameter("name", "18021283352")
                .addParameter("password", "dxy@170701")
                .addParameter("remember", "false")
                .addParameter("ticket", "")
                .addParameter("ck", "")
                .build();
        // 模拟登陆
        CloseableHttpResponse response = httpclient.execute(login);

        if (response.getStatusLine().getStatusCode() == 200) {
            // 构造访问个人中心请求
            HttpGet httpGet = new HttpGet(userInfoUrl);
            CloseableHttpResponse user_response = httpclient.execute(httpGet);
            HttpEntity entity = user_response.getEntity();
            //
            String body = EntityUtils.toString(entity, "utf-8");

            // 偷个懒，直接判断 缺心眼那叫单纯 是否存在字符串中
            System.out.println("缺心眼那叫单纯是否查找到？" + (body.contains("缺心眼那叫单纯")));
        } else {
            System.out.println("httpclient 模拟登录豆瓣失败了!!!!");
        }
    }

}
